package org.sword.wechat4j;

import org.apache.commons.lang3.StringUtils;
import org.apache.log4j.Logger;
import org.sword.wechat4j.type.EventType;
import org.sword.wechat4j.type.MsgType;
import org.sword.wechat4j.param.SignatureParam;
import org.sword.wechat4j.request.WechatRequest;
import org.sword.wechat4j.response.ImageResponse;
import org.sword.wechat4j.response.VoiceResponse;
import org.sword.wechat4j.response.WechatResponse;
import org.sword.wechat4j.util.SerializeXmlUtil;

import javax.servlet.http.HttpServletRequest;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;


/**
 * @author ChengNing
 */
@Deprecated
public abstract class WechatSupport {

    public static final Logger logger = Logger.getLogger(WechatSupport.class);

    private HttpServletRequest request;
    private String postData;
    private String token;

    protected WechatRequest wechatRequest;
    protected WechatResponse wechatResponse;


    /**
     * 构建微信处理
     *
     * @param request 微信服务发过来的http请求
     * @param token   token
     */
    public WechatSupport(HttpServletRequest request, String token) {
        this.request = request;
        this.token = token;
        this.wechatRequest = new WechatRequest();
        this.wechatResponse = new WechatResponse();
    }

    /**
     * wechat调用入口，进行数据接收，事件分发
     *
     * @return responseXML
     */
    public String run() {
        return run(new SignatureParam(request));
    }
    public String run(SignatureParam param) {
        logger.debug("WechatSupport run");
        String signature = param.getSignature();
        String timestamp = param.getTimestamp();
        String nonce = param.getNonce();
        String echostr = param.getEchostr();

        ValidateSignature validateSignature = new ValidateSignature(signature,
                timestamp, nonce, this.token);
        if (!validateSignature.check()) {
            return "error";
        }
        if (StringUtils.isNotBlank(echostr)) {
            return echostr;
        }
        //分发消息，得到响应
        String result = distribute();
        logger.debug("response data:" + result);
        return result;
    }

    /**
     * 分发处理，得到响应
     *
     * @return responseXML
     */
    private String distribute() {
        try {
//            postDataStr = stream2String(request.getInputStream());
            postData = readString(request.getReader());
        } catch (IOException e) {
            logger.error("post data deal failed!", e);
        }
        // 解析数据
        setPostData();
        // 消息分发处理
        distributeMessage();
        // 响应事件
        return response();
    }

    private String readString(BufferedReader reader) throws IOException {
        StringBuilder sb = new StringBuilder();
        String tmp;
        while ((tmp = reader.readLine()) != null) {
            sb.append(tmp);
        }
        return sb.toString();
    }


    private String stream2String(InputStream is) {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        int i;
        try {
            while ((i = is.read()) != -1) {
                baos.write(i);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
        return baos.toString();
    }

    /**
     * 得到post数据，对象化
     *
     */
    private void setPostData() {
        logger.info("parse post data");
        try {
            this.wechatRequest = SerializeXmlUtil.toObj(postData, WechatRequest.class);
        } catch (Exception e) {
            logger.error("post data parse error", e);
        }
    }

    /**
     * 消息事件分发
     */
    public void distributeMessage() {
        logger.debug("distributeMessage start");
        if (StringUtils.isBlank(wechatRequest.getMsgType())) {
            logger.warn("msgType is null");
        }
        MsgType msgType = MsgType.valueOf(wechatRequest.getMsgType());
        switch (msgType) {
            case event:
                distributeEvent();
                break;
            case text:
                onText();
                break;
            case image:
                onImage();
                break;
            case location:
                onLocation();
                break;
            case link:
                onLink();
                break;
            case video:
                onVideo();
                break;
            case voice:
                onVoice();
                break;
            case shortvideo:
                onShortVideo();
                break;
            default:
                onUnknown();
                break;
        }

    }

    /**
     * event事件分发
     */
    private void distributeEvent() {
        EventType event = EventType.valueOf(wechatRequest.getEvent());
        switch (event) {
            case CLICK:
                click();
                break;
            case subscribe:
                subscribe();
                break;
            case unsubscribe:
                unSubscribe();
                break;
            case SCAN:
                scan();
                break;
            case LOCATION:
                location();
                break;
            case VIEW:
                view();
                break;
            case MASSSENDJOBFINISH:
                massSendJobFinish();
                break;
            case TEMPLATESENDJOBFINISH:
                templateSendJobFinish();
                break;
            default:
                break;
        }

    }

    /**
     * 返回响应数据
     *
     * @return responseXML
     */
    private String response() {
        responseBase();
        String result = null;
        try {
            result = SerializeXmlUtil.toXML(wechatResponse);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    /**
     * 响应数据基础构造
     */
    private void responseBase() {
        wechatResponse.setToUserName(this.wechatRequest.getFromUserName());
        wechatResponse.setFromUserName(wechatRequest.getToUserName());
        wechatResponse.setCreateTime(wechatRequest.getCreateTime());
    }

    /**
     * 文本消息响应
     *
     * @param content 文本信息
     */
    public void responseText(String content) {
        wechatResponse.setContent(content);
    }

    /**
     * 图片消息响应
     * @param mediaId 素材
     */
    public void responseImage(String mediaId) {
        ImageResponse image = new ImageResponse();
        image.setMediaId(mediaId);
        wechatResponse.setImage(image);
    }

    /**
     * 语音消息响应
     * @param mediaId 素材
     */
    public void responseVoice(String mediaId) {
        VoiceResponse voice = new VoiceResponse();
        voice.setMediaId(mediaId);
        wechatResponse.setVoice(voice);
    }


    /**
     * 文本消息处理
     */
    protected abstract void onText();

    /**
     * 图像
     */
    protected abstract void onImage();

    /**
     * location消息处理msgtype=location
     */
    protected abstract void onLocation();

    /**
     * link消息处理
     */
    protected abstract void onLink();

    /**
     * shortvideo消息处理
     */
    protected abstract void onShortVideo();

    /**
     * voice消息处理
     */
    protected abstract void onVoice();

    /**
     * video消息处理
     */
    protected abstract void onVideo();

    /**
     * 未知消息类型的错误处理逻辑，不需要处理则空方法即可
     */
    protected abstract void onUnknown();


    /**
     * click点击事件处理
     */
    protected abstract void click();

    /**
     * subscribe关注事件处理
     */
    protected abstract void subscribe();

    /**
     * unSubscribe取消关注事件处理
     */
    protected abstract void unSubscribe();

    /**
     * scan事件处理
     */
    protected abstract void scan();

    /**
     * location事件处理event=location
     */
    protected abstract void location();

    /**
     * view 事件处理
     */
    protected abstract void view();

    /**
     * 群发结果通知 事件处理
     */
    protected abstract void massSendJobFinish();

    /**
     * 模板消息推送结果通知 事件处理
     */
    protected abstract void templateSendJobFinish();
}
